package com.csaba.connector.otp.parser;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Currency;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.TextExtractor;

import com.csaba.connector.model.Account;
import com.csaba.connector.model.Amount;
import com.csaba.connector.model.Customer;
import com.csaba.connector.otp.model.OTPBank;
import com.csaba.util.LoggerHelper;

public class AccountBalanceParser
{
	public static final String ACCOUNT_INDEX = "account.index";

	private final static Logger logger = LoggerHelper.getDefaultLogger();

	public static Account[] extractAccountList( final Reader accountListReply, final Customer customer )
			throws IOException
	{
		final Source source = new Source(accountListReply);

		final List<Element> balances = source.getAllElementsByClass("balance");
		final Account[] result = new Account[balances.size()];
		int i = -1;
		for ( final Element balance : balances )
		{
			i++;

			final Element a = balance.getFirstElement("a");
			if ( a == null )
			{
				//item remains null
				logger.warning("Missing balance for URL for balance: " + new TextExtractor(balance).toString());
				continue;
			}

			//TODO extract account type here
			final String url = a.getAttributeValue("href");
			final int accountNumberIndex = url.indexOf("accountNumber=");
			if ( accountNumberIndex < 0 )
			{
				//item remains null
				logger.warning("Missing account number for URL for balance: " + new TextExtractor(balance).toString());
				continue;
			}

			final String accountNumber = url.substring(url.indexOf("=", accountNumberIndex) + 1);

			result[i] = new Account();
			result[i].setBank(OTPBank.getInstance());
			result[i].setCustomer(customer);
			result[i].setNumber(accountNumber);
			result[i].setRemoteProperty(OTPCodes.RP_ACCOUNT_DETAILS_URL, url);
		}

		return result;
	}

	public static Account extractAccountDetails( final Reader accountDetailsReply, final Account account )
			throws IOException, ParseException
	{
		final Source source = new Source(accountDetailsReply);

		final List<Element> rows = source.getAllElementsByClass("formrow");
		for ( final Element row : rows )
		{
			final Element title = row.getFirstElementByClass("title");
			if ( title == null )
				continue;
			String titleText = new TextExtractor(title).toString();

			int colonIndex = titleText.indexOf(":");
			while ( colonIndex >= 0 )
			{
				titleText = titleText.substring(0, colonIndex) + titleText.substring(colonIndex + 1);
				colonIndex = titleText.indexOf(":");
			}

			final Element value = row.getFirstElementByClass("values");
			if ( value == null )
			{
				logger.warning("Missing value for account detail (title): " + titleText);
				continue;
			}

			final String valueText = new TextExtractor(value).toString();
			logger.fine("Account detail is found: " + titleText + " = " + valueText);

			if ( "Könyvelt egyenleg".equals(titleText) )
			{
				//		booked > Könyvelt egyenleg = 424.637 HUF
				account.setBookedBalance(parseAmount(valueText));
			}
			else if ( "Rendelkezésre álló egyenleg".equals(titleText) )
			{
				//		available >	Rendelkezésre álló egyenleg = 379.355 HUF
				account.setAvailableBalance(parseAmount(valueText));
			}
			else if ( "Számla elnevezése".equals(titleText) || "Számla név".equals(titleText) )
			{
				//		name >	Számla elnevezése = XXXX
				//		name >	Számla név = XXXXX
				account.setName(valueText);
			}
			else if ( "Számlaszám".equals(titleText) )
			{
				//		number > Számlaszám = 11111111-22222222-11111111 HUF
				final int space = valueText.indexOf(" ");
				if ( space < 0 )
				{
					account.setNumber(valueText);
					account.setCurrency(OTPBank.getInstance().getBaseCurrency());
				}
				else
				{
					account.setNumber(valueText.substring(0, space));
					account.setCurrency(Currency.getInstance(valueText.substring(space + 1)));
				}
			}
			else
			{
				account.setRemoteProperty(titleText, parseGeneral(valueText));
			}
		}
		return account;
	}

	private static Object parseGeneral( final String valueText )
	{
		// FIXME detect value type and parse value
		return valueText;
	}

	private static Amount parseAmount( final String valueText ) throws ParseException
	{
		// parse amount (sample):  424.637 HUF
		final int space = valueText.indexOf(" ");

		String numberPart = valueText;
		Currency currency = OTPBank.getInstance().getBaseCurrency();
		if ( space > 0 )
		{
			numberPart = valueText.substring(0, space);
			currency = Currency.getInstance(valueText.substring(space + 1));
		}

		final DecimalFormat df = new DecimalFormat("#,##0.#");
		final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
		dfs.setGroupingSeparator('.');
		dfs.setDecimalSeparator(',');
		df.setDecimalFormatSymbols(dfs);

		final double amount = df.parse(numberPart).doubleValue();
		return new Amount(amount, currency);
	}

	/**
	 * @param args
	 * @throws IOException
	 * @throws MalformedURLException
	 * @throws ParseException
	 */
	public static void main( final String[] args ) throws MalformedURLException, IOException, ParseException
	{
		LoggerHelper.initLogger(Level.FINE);

		final Customer customer = new Customer();
		customer.setBank(OTPBank.getInstance());
		customer.setName("Dummy User");

		//		final FileInputStream fis = new FileInputStream("../otp.source/accountListReply.html");
		//		final Account[] account = extractAccountList(new InputStreamReader(fis, OTPCodes.HTML_CHARSET), customer);
		//		for ( final Account acc : account )
		//		{
		//			logger.info("acc: " + acc);
		//		}

		final Account account = new Account();
		account.setNumber("12345");
		account.setBank(OTPBank.getInstance());
		account.setCustomer(customer);

		final FileInputStream fis = new FileInputStream("../otp.source/accountDetails2Reply.html");
		extractAccountDetails(new InputStreamReader(fis, OTPCodes.HTML_CHARSET), account);
		logger.info("Account: " + account);
	}

	//		booked > Könyvelt egyenleg = 424.637 HUF
	//		available >	Rendelkezésre álló egyenleg = 379.355 HUF
	//		name >	Számla elnevezése = XXXX
	//		name >	Számla név = XXXXX
	//		number > Számlaszám = 11111111-22222222-11111111 HUF

	//	Előjegyzett bruttó betéti kamat = 55 HUF
	//	Előjegyzett hitel- és ügyleti kamat = 3.044 HUF
	//	Előjegyzett kártyaforgalmak = -42.307 HUF
	//	Előjegyzett kártyaforgalom = 0 HUF
	//	Előjegyzett visszatérítés = 0 HUF
	//	Elszámolás időpontja (utolsó kivonat dátuma) = 2012.05.10.
	//	Elszámolási időszak kezdete = 2012.05.11.
	//	Elszámolási időszak nyitó egyenlege = -259.963 HUF
	//	Elszámolási időszakban fizetett összeg = 12.998 HUF
	//	Engedélyezett hitelkeret = 450.000 HUF
	//	Felhasználható hitelkeret = 203.035 HUF
	//	Fizetés teljesítésének módja = Automatikus
	//	Fizetési határidő = 2012.05.25.
	//	Hitelkeret = 0 HUF
	//	Hitelkeret = 800.000 HUF
	//	Hitelkeret túlhívás = 0 HUF
	//	Jelenleg fennálló tartozás = -246.965 HUF
	//	Készpénzfelvételi kamatláb(%) = 30.72
	//	Lekötött betétek = 0 HUF
	//	Minimum fizetendő összeg = 12.998 HUF
	//	Multipont egyenleg = 0 HUF
	//	Számla státusz = Aktív
	//	Túlfizetési egyenleg = 0 HUF
	//	Vásárlási kamatláb(%) = 30.72
	//	Zárolások összege = 0 HUF
	//	Zárolások összesen = 2.975 HUF
}
